import type { UserInfo } from '/#/store';
import type { ErrorMessageMode } from '/#/axios';
import { defineStore } from 'pinia';
import { store } from '/@/store';
import { RoleEnum } from '/@/enums/roleEnum';
import { PageEnum } from '/@/enums/pageEnum';
import {
  UAC_ROLES_KEY,
  UAC_TOKEN_KEY,
  UAC_USER_VALID_PROJECTS_KEY,
  UAC_USER_CURRENT_PROJECT_KEY,
  UAC_USER_CURRENT_PROJECT_CODE_KEY,
  UAC_USER_INFO_KEY,
  UAC_LOGIN_PROMPT_KEY,
} from '/@/enums/cacheEnum';
import { getAuthCache, setAuthCache } from '/@/utils/auth';
import { UacUserInfoDto, LoginDto, UserModifyPasswordDto } from '/@/api/platform/model/userModel';
import { ObjectParamValuesDto } from '/@/api/platform/paramValueModel';
import { doLogout, getUserInfo, login, modifyPassword } from '/@/api/platform/uac';
import { useI18n } from '/@/hooks/web/useI18n';
import { useMessage } from '/@/hooks/web/useMessage';
import { router } from '/@/router';
import { usePermissionStore } from '/@/store/modules/permission';
import { useAppStoreWithOut } from '/@/store/modules/app';
import { RouteRecordRaw } from 'vue-router';
import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
import { isArray } from '/@/utils/is';
import { h } from 'vue';
import { getAppEnvConfig } from '/@/utils/env';
const {
  VITE_GLOB_APP_PROJECT_CODE,
} = getAppEnvConfig();
interface UserState {
  userInfo: Nullable<UserInfo>;
  token?: string;
  projects?: ObjectParamValuesDto[];
  project: Nullable<ObjectParamValuesDto>;
  projectCode?: string;
  roleList: RoleEnum[];
  sessionTimeout?: boolean;
  lastUpdateTime: number;
  loginPrompt?: string;
}

export const useUserStore = defineStore({
  id: 'app-user',
  state: (): UserState => ({
    // user info
    userInfo: null,
    // token
    token: undefined,
    //用户可用的项目信息列表
    projects: [],
    //用户当前使用的项目信息，用于前端显示系统logo、标题、版权信息
    project: null,
    //用户当前使用的项目编码
    projectCode: undefined,
    // roleList
    roleList: [],
    // Whether the login expired
    sessionTimeout: false,
    // Last fetch time
    lastUpdateTime: 0,
    //用户登录结果提示信息--用于存放重要通知消息（如需要修改密码）
    loginPrompt: undefined,
  }),
  getters: {
    getUserInfo(): UserInfo {
      return this.userInfo || getAuthCache<UserInfo>(UAC_USER_INFO_KEY) || {};
    },
    getToken(): string {
      return this.token || getAuthCache<string>(UAC_TOKEN_KEY);
    },
    getUserValidProjects(): ObjectParamValuesDto[] {
      return this.projects?.length > 0 ? this.projects : getAuthCache<ObjectParamValuesDto[]>(UAC_USER_VALID_PROJECTS_KEY);
    },
    getUserCurrentProject(): ObjectParamValuesDto {
      return this.project || getAuthCache<ObjectParamValuesDto>(UAC_USER_CURRENT_PROJECT_KEY);
    },
    getUserCurrentProjectCode(): string {
      let code = VITE_GLOB_APP_PROJECT_CODE || this.projectCode || getAuthCache<string>(UAC_USER_CURRENT_PROJECT_CODE_KEY);
      console.log('src\\store\\modules\\user.ts getUserCurrentProjectCode', code);
      return code;
    },
    getRoleList(): RoleEnum[] {
      return this.roleList?.length > 0 ? this.roleList : getAuthCache<RoleEnum[]>(UAC_ROLES_KEY);
    },
    getSessionTimeout(): boolean {
      return !!this.sessionTimeout;
    },
    getLastUpdateTime(): number {
      return this.lastUpdateTime;
    },
    getLoginPrompt(): string {
      return this.loginPrompt || getAuthCache<string>(UAC_LOGIN_PROMPT_KEY);
    },
  },
  actions: {
    setToken(info: string | undefined): void {
      this.token = info ? info : ''; // for null or undefined value
      setAuthCache(UAC_TOKEN_KEY, info);
    },
    setUserValidProjects(projects: ObjectParamValuesDto[] | null): void {
      this.projects = projects;
      console.log('setUserValidProjects', projects);
      setAuthCache(UAC_USER_VALID_PROJECTS_KEY, projects);
    },
    setUserCurrentProject(project: ObjectParamValuesDto | null): void {
      console.log('src\\store\\modules\\user.ts setUserCurrentProject', project);
      this.project = project;
      setAuthCache(UAC_USER_CURRENT_PROJECT_KEY, project);
    },
    setUserCurrentProjectCode(code: string | undefined): void {
      console.log('src\\store\\modules\\user.ts setUserCurrentProjectCode', code);
      this.projectCode = code ? code : ''; // for null or undefined value
      setAuthCache(UAC_USER_CURRENT_PROJECT_CODE_KEY, code);
    },
    setRoleList(roleList: RoleEnum[]): void {
      this.roleList = roleList;
      setAuthCache(UAC_ROLES_KEY, roleList);
    },
    setUserInfo(info: UserInfo | null): void {
      this.userInfo = info;
      this.lastUpdateTime = new Date().getTime();
      setAuthCache(UAC_USER_INFO_KEY, info);
    },
    setSessionTimeout(flag: boolean) {
      this.sessionTimeout = flag;
    },
    setLoginPrompt(info: string | undefined): void {
      this.loginPrompt = info ? info : '';
      setAuthCache(UAC_LOGIN_PROMPT_KEY, info);
    },
    resetState() {
      this.userInfo = null;
      this.token = '';
      //在src\router\guard\stateGuard.ts中每次路由跳转时会调用resetState方法，即路由跳转时会重置store中的信息
      //需要特别注意选择放在此方法中的赋值代码，可能造成store中的数据被清除
      //2024-3-13，修改为不对当前项目编码和当前项目信息进行重置
      // this.projectCode = '';
      this.roleList = [];
      this.sessionTimeout = false;
      this.loginPrompt = '';
    },
    async qclogin(
      params: LoginDto & {
        goHome?: boolean;
        mode?: ErrorMessageMode;
      },
    ): Promise<LoginResultDto | null> {
      try {
        const { goHome = true, mode, ...loginParams } = params;
        const data = await login(loginParams, mode);

        //返回登录结果数据
        return data;
      } catch (error) {
        return Promise.reject(error);
      }
    },
    /**
     * @description: login
     */
    async login(
      params: LoginDto & {
        goHome?: boolean;
        mode?: ErrorMessageMode;
      },
    ): Promise<UacUserInfoDto | null> {
      //修改原有代码，使用qclogin替换
    },
    /**
     * @description: 登录后的处理动作：获取用户信息、设置路由、设置菜单
     */
    async afterLoginAction(
      goHome?: boolean,
      redirectRouter?: string,
    ): Promise<UacUserInfoDto | null> {
      //如果没有token，表示登录不成功，不需要继续处理
      if (!this.getToken) return null;
      //获取用户信息
      const userInfo = await this.getUserInfoAction();
      // userInfo == null 说明token过期或无效，需要重新登录, 不获取menu直接跳转到login
      if (userInfo == null) return router.replace(PageEnum.BASE_LOGIN);

      const sessionTimeout = this.sessionTimeout;
      if (sessionTimeout) {
        this.setSessionTimeout(false);
      } else {
        //设置路由
        const permissionStore = usePermissionStore();
        //记录从buildRoutesAction中得到的第一个有效路由（不为404、login、home、error的路由）
        let defaultBuildRoute = undefined;
        if (!permissionStore.isDynamicAddedRoute) {
          // 得到路由的列表，做循环处理，设置登录跳转
          const routes = await permissionStore.buildRoutesAction();
          console.log('routes路由列表', routes);
          routes.forEach((route) => {
            router.addRoute(route as unknown as RouteRecordRaw);
            //判断路由是否有效
            if (defaultBuildRoute === undefined || defaultBuildRoute === null) {
              if (route.path != PAGE_NOT_FOUND_ROUTE.path
                && route.path != PageEnum.BASE_LOGIN
                && route.path != PageEnum.HOME
                && route.path != PageEnum.ERROR_PAGE
                && route.path != PageEnum.ERROR_LOG_PAGE
                && (route.children === undefined || route.children === null)
                && (route.component?.toString().includes('/')
                  && route.meta.hideMenu === false)) {//要求没有下级路由
                //forEach方法无法使用break跳出循环，赋值时进行判断，如果有值不进行在此赋值
                if (defaultBuildRoute === undefined || defaultBuildRoute === null) {
                  defaultBuildRoute = route.path;
                  console.log('route赋值1,', route.path, route.name)
                }

              }
            }
            //如果有子级路由，判断子级路由信息
            if (defaultBuildRoute === undefined || defaultBuildRoute === null) {
              if (route.children != undefined && route.children != null && route.children.length > 0x0) {
                route.children.forEach((level2Route) => {
                  if (level2Route.path != PAGE_NOT_FOUND_ROUTE.path
                    && level2Route.path != PageEnum.BASE_LOGIN
                    && level2Route.path != PageEnum.HOME
                    && level2Route.path != PageEnum.ERROR_PAGE
                    && level2Route.path != PageEnum.ERROR_LOG_PAGE
                    && (level2Route.children === undefined || level2Route.children === null)
                    && (level2Route.component?.toString().includes('/')
                      && level2Route.meta.hideMenu === false)) {//要求没有下级路由
                    //forEach方法无法使用break跳出循环，赋值时进行判断，如果有值不进行在此赋值
                    if (defaultBuildRoute === undefined || defaultBuildRoute === null) {
                      defaultBuildRoute = level2Route.path;
                      console.log('route赋值2,', level2Route.path, level2Route.name)
                    }
                  }
                });
              }
            }
          });
          router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw);
          permissionStore.setDynamicAddedRoute(true);
        }

        console.log('afterLoginAction goHome=' + goHome + ' redirectRouter' + redirectRouter + ' defaultBuildRoute=' + defaultBuildRoute);
        //登录成功后跳转路由顺序：(重定向路由、后台指定的路由、上次访问的菜单路由、路由表中的第1个、HOME)：redirectRouter、userInfo?.homePath、跳转路由为根路由/（store中记录的上次路由、得到的路由列表routes中的第1个）、HOME
        if (!redirectRouter) {
          //指定的登录跳转路由为空
          if (!userInfo?.homePath) {
            //后台接口返回在用户信息中的路由地址为空
            const storeMenuRoute = useAppStoreWithOut().getMenuRoute;
            console.log('storeMenuRoute ', storeMenuRoute);
            if (!storeMenuRoute) {
              //Store中记录的用户上次点击菜单的路由为空
              //如果得到的最终路由表不为空，默认使用第1个路由进行跳转
              if (!defaultBuildRoute) {
                //在buildRoutesAction方法中得到的默认路由为空，跳转到Home，不需要进行处理
                await router.replace(PageEnum.HOME);
              }
              else {
                //在buildRoutesAction方法中得到的默认路由不为空
                await router.replace(defaultBuildRoute);
                useAppStoreWithOut().setMenuRoute(defaultBuildRoute);
              }
            }
            else {
              //Store中记录的用户上次点击菜单的路由不为空，跳转到上次使用的模块路由
              console.log(storeMenuRoute, 'storeMenuRoute route')
              await router.replace(storeMenuRoute);
              useAppStoreWithOut().setMenuRoute(storeMenuRoute);
            }
          }
          else {
            //后台接口返回在用户信息中的路由地址不为空，跳转到后台返回的路由地址
            await router.replace(userInfo?.homePath);
            useAppStoreWithOut().setMenuRoute(userInfo?.homePath);
          }
        }
        else {
          //指定的登录跳转路由不为空，登录成功后进行跳转
          await router.replace(redirectRouter);
          useAppStoreWithOut().setMenuRoute(redirectRouter);
        }
      }

      return userInfo;
    },
    async getUserInfoAction(): Promise<UserInfo | null> {
      console.log('src\\store\\modules\\user.ts getUserInfoAction');
      if (!this.getToken) {
        console.log('src\\store\\modules\\user.ts getUserInfoAction getToken 从store中未能获取到token');
        return null;
      }
      const uacUserInfo = await getUserInfo();
      console.log('src\\store\\modules\\user.ts getUserInfoAction getUserInfo 根据token获取用户信息为：', uacUserInfo);
      //渠成用户权限中不需要前端记录角色roles信息
      // const { roles = [] } = userInfo;
      // if (isArray(roles)) {
      //   const roleList = roles.map((item) => item.value) as RoleEnum[];
      //   this.setRoleList(roleList);
      // } else {
      //   userInfo.roles = [];
      //   this.setRoleList([]);
      // }
      //判断后台Uac获取的用户信息是否为空
      if (!uacUserInfo) {
        console.log('src\\store\\modules\\user.ts getUserInfoAction getUserInfo 根据token获取用户信息为空，准备清除store');
        //根据token获取到的用户信息为空时表示token无效或者其他错误，需要将store中的token进行清空
        this.clearUacStore();
        return null;
      }
      else {
        let custominfo = uacUserInfo.custominfo;
        if (custominfo) {
          try {
            custominfo = JSON.parse(custominfo);
          } catch (e) { }
        } else {
          custominfo = {};
        }
        //将后台Uac用户信息转换为store中的用户信息
        let userInfo: UserInfo = {
          // userId: uacUserInfo.id,
          username: uacUserInfo.code,
          realName: uacUserInfo.name,
          avatar: custominfo?.avatar ?? '',
          sign: custominfo?.sign ?? '',
        };
        this.setUserInfo(userInfo);
        //判断是否有项目编码信息，如果store中没有项目编码信息使用获取用户信息接口中的项目编码进行更新
        if (!this.getUserCurrentProjectCode) {
          this.setUserCurrentProjectCode(uacUserInfo.project);
        }

        return userInfo;
      }
    },
    /**
     * @description: 退出登录，清除token、项目编码等信息
     */
    async logout(goLogin = false) {
      if (this.getToken) {
        try {
          await doLogout();
        } catch {
          console.log('注销Token失败');
        }
      }
      //清除store中的信息
      this.clearUacStore();
      // useAppStoreWithOut().clearMenuRoute();
      let storeProjectCode = this.getUserCurrentProjectCode;
      console.log('user.ts after logout storeProjectCode=' + storeProjectCode);
      //跳转至登录界面
      goLogin && router.push(PageEnum.BASE_LOGIN);
    },
    /**
    * @description: 清除store中的uac信息，包含token、用户信息、项目信息、菜单信息
    */
    clearUacStore() {
      this.setSessionTimeout(false);
      this.setToken(undefined);
      this.setUserValidProjects(null);
      useAppStoreWithOut().clearMenuRoute();
      //2024-3-13，修改为：登录失败不清除store中的用户当前项目和项目编码；
      //清除后如果跳转回登录界面没有项目编码使用env中的项目编码会导致用户与所在项目信息不匹配无法登录;
      // this.setUserCurrentProject(null);
      // this.setUserCurrentProjectCode(undefined);
      this.setUserInfo(null);
    },
    /**
     * @description: Confirm before logging out
     */
    confirmLoginOut() {
      const { createConfirm } = useMessage();
      const { t } = useI18n();
      createConfirm({
        iconType: 'warning',
        title: () => h('span', t('sys.app.logoutTip')),
        content: () => h('span', t('sys.app.logoutMessage')),
        onOk: async () => {
          await this.logout(true);
        },
      });
    },
    async modifyPassword(params: UserModifyPasswordDto) {
      const data = await modifyPassword(params);

      return data;
    },
    validateRoute(path) {
      // 封装一个统一验证方法，用于验证指定的路由是否在用户有访问权限的菜单集合中；
      // 用于界面中可能有的点击在跳转前验证是否有访问权限，避免跳转后出现404页面问题；
      if (router.getRoutes().filter(r => !r.meta.hideMenu).filter(item => item.path == path).length > 0) {
        return true;
      } else {
        return false;
      }
    }
  },
});

// Need to be used outside the setup
export function useUserStoreWithOut() {
  return useUserStore(store);
}
